package com.opensource.component.validate;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.groups.Default;
import org.apache.commons.collections4.CollectionUtils;

/**
 * @author zhanglong
 * @since 2019-08-31 12:33
 */
public class ValidationExecutor {

    private Validator validator;

    /**
     * description 默认校验器 校验集合
     */
    public <T> ValidationListResult<T> validateList(List<T> dataList) {
        return validateList(dataList, null);


    }

    /**
     * description 自定义校验器 校验集合
     */
    public <T> ValidationListResult<T> validateList(List<T> dataList,
                                                    Validator validator) {
        if (Objects.isNull(validator)) {
            validator = Validation.buildDefaultValidatorFactory().getValidator();
        }
        ValidationListResult<T> result = new ValidationListResult<>();
        if (CollectionUtils.isEmpty(dataList)) {
            return result;
        }
        Validator finalValidator = validator;
        for (T t : dataList) {
            Map<String, String> errorMsg = new HashMap<>(dataList.size());
            catchErrorMsg(t, finalValidator, errorMsg);
            if (errorMsg.isEmpty()) {
                result.getSuccessData().add(t);
            } else {
                result.getErrorData().put(t, errorMsg);
            }
        }
        return result;
    }

    /**
     * description 自定义校验器 校验对象
     */
    public <T> ValidationEntityResult<T> validateEntity(T data) {
        if (Objects.isNull(validator)) {
            validator = Validation.buildDefaultValidatorFactory().getValidator();
        }
        ValidationEntityResult<T> validationEntityResult = new ValidationEntityResult<>();
        if (Objects.isNull(data)) {
            return validationEntityResult;
        }
        validationEntityResult.setData(data);
        final Map<String, String> errorMsgMap = validationEntityResult.getErrorMsg();
        catchErrorMsg(data, validator, errorMsgMap);
        return validationEntityResult;
    }

    /**
     * description 抓取错误信息
     */
    private <T> void catchErrorMsg(T data, Validator validator, Map<String, String> errorMsgMap) {
        Set<ConstraintViolation<T>> constraintViolationSet = validator
                .validate(data, Default.class);
        for (ConstraintViolation<T> constraintViolation : CollectionUtils.emptyIfNull(constraintViolationSet)) {
            final String key = constraintViolation.getPropertyPath().toString();
            if (errorMsgMap.containsKey(key)) {
                errorMsgMap.put(key, errorMsgMap.get(key) + ";" + constraintViolation.getMessage());
            } else {
                errorMsgMap.put(key, constraintViolation.getMessage());
            }
        }
    }

}
